package com.hutu.interceptor;
import cn.hutool.core.collection.CollectionUtil;
import com.hutu.common.ErrorCode;
import com.hutu.constant.UserConstant;
import com.hutu.exception.BusinessException;
import com.hutu.exception.ThrowUtils;
import com.hutu.properties.JwtProperties;
import com.hutu.utils.JwtUtils;
import com.hutu.utils.UserThreadLocal;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.Objects;

@Component
@RequiredArgsConstructor
public class UserInterceptor implements HandlerInterceptor {
    private final JwtProperties jwtProperties;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("accessToken");
        Long tokenId = null;
        Map<String, Object> checkToken = null;
        // 如果是没有token，则抛出异常,让其登录
        ThrowUtils.throwIf(StringUtils.isBlank(token), ErrorCode.NOT_LOGIN_ERROR);
        try{
            checkToken = JwtUtils.checkToken(token, jwtProperties.getPublicKey());
        } catch (Exception e){
            // 如果是解析错误,那么就是错误的token(非法请求,需要让其登录)
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        // 如果解析的token为null,那么表示该token已过期,需要刷新token
        if (CollectionUtil.isEmpty(checkToken)){
            throw new BusinessException(ErrorCode.PARSE_ERROR);
        }
        tokenId = (Long) checkToken.getOrDefault(UserConstant.USER_TOKEN_ID, "");
        if (Objects.isNull(tokenId)) {
            throw new BusinessException(ErrorCode.PARSE_ERROR);
        }
        UserThreadLocal.set(tokenId);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserThreadLocal.remove();
    }
}
